package com.xu.t1.service;

import com.fasterxml.jackson.core.type.TypeReference;
import com.xu.t1.common.RedisLockUtil;
import com.xu.t1.common.RedisCache;
import com.xu.t1.mapper.LearningRecordMapper;
import com.xu.t1.mapper.UserMapper;
import com.xu.t1.model.LearningRecord;
import com.xu.t1.model.PageResult;
import com.xu.t1.model.UploadLog;
import com.xu.t1.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 学习记录表的基本业务逻辑
 *
 * @author xu
 *
 */



@Service
public class LearningRecordService {

    @Autowired
    private RedisLockUtil redisLockUtil;
    @Autowired
    private LearningRecordTxService txService;
    @Autowired
    private LearningRecordMapper learningRecordMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisCache redisCache;


    // 插入操作失败时候的二次尝试，可以改成多次尝试
    public boolean saveWithRetry(List<LearningRecord> records) {
        boolean success = txService.saveRecords(records);
        if (!success) {
            // 你可以将重试次数做成参数
            success = txService.saveRecords(records);
        }
        return success;
    }


    // 删除补偿操作
    public int deleteRecords(Long Id) {
        return learningRecordMapper.deleteRecordById(Id);
    }

    // 更新用户的record_count字段值 乐观锁
    public boolean updateRecordCountOptimistic(Long userId, int delta, int maxRetry, UploadLog log) {
        UploadLog.OptimisticLockInfo lockInfo = new UploadLog.OptimisticLockInfo();

        for (int i = 1; i <= maxRetry; i++) {
            User user = userMapper.findUserById(userId);
            if (user == null) {

                lockInfo.setTryCount(i - 1);
                lockInfo.setSuccess(false);
                log.setOptimisticLock(lockInfo);
                return false; // 用户不存在
            }
            int currentVersion = user.getVersion();

            int updatedRows = userMapper.increaseRecordCount(userId, delta, currentVersion);
            if (updatedRows == 1) {

                lockInfo.setTryCount(i);
                lockInfo.setSuccess(true);
                log.setOptimisticLock(lockInfo);
                return true; // 成功
            }
        }

        lockInfo.setTryCount(maxRetry);
        lockInfo.setSuccess(false);
        log.setOptimisticLock(lockInfo);
        return false; // 重试次数耗尽，失败
    }

    //带分布式锁的乐观锁更新，最多重试3次，每次间隔1秒
    public boolean updateRecordCountWithLockAndRetry(Long userId, int totalSize, UploadLog log) {
        String lockKey = "lock:updateRecord:" + userId;
        int maxRetries = 3;
        int retryIntervalMillis = 1000;

        UploadLog.DistributedLockInfo lockInfo = new UploadLog.DistributedLockInfo();

        for (int attempt = 1; attempt <= maxRetries; attempt++) {
            boolean result = redisLockUtil.runWithLock(lockKey, () -> {

                // 调用乐观锁更新方法
                return updateRecordCountOptimistic(userId, totalSize, 3, log);
            }, false);

            if (result) {

                //记录尝试次数和成功
                lockInfo.setTryCount(attempt);
                lockInfo.setSuccess(true);
                log.setDistributedLock(lockInfo);

                return true;  // 成功直接返回
            } else {
                System.out.println("第 " + attempt + " 次尝试更新失败，等待后重试...");
                try {
                    Thread.sleep(retryIntervalMillis);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
        }

        lockInfo.setTryCount(maxRetries);
        lockInfo.setSuccess(false);
        log.setDistributedLock(lockInfo);


        // 重试3次均失败
        return false;
    }


    //分页查询学习记录的业务逻辑
    public PageResult<LearningRecord> getRecordsByUserIdPaged(Long userId, int page, int size) {
        // 计算偏移量
        int offset = (page - 1) * size;

        // 查询数据列表
        List<LearningRecord> records = learningRecordMapper.findRecordsByUserIdPaged(userId, offset, size);

        // 查询总数
        int total = learningRecordMapper.countByUserId(userId);

        // 返回分页结果
        return new PageResult<>(total, records);
    }

    public PageResult<LearningRecord> getRecordsByUserIdPagedWithCache(Long userId, int page, int size) {
        String cacheKey = "learning:records:" + userId + ":page:" + page + ":size:" + size;

        // 尝试从 Redis 读取缓存
        PageResult<LearningRecord> cache = redisCache.get(cacheKey, new TypeReference<PageResult<LearningRecord>>() {
        });
        if (cache != null) {
            cache.setSource("redis");
            return cache; // 命中缓存
        }

        // 缓存未命中，走数据库查询
        PageResult<LearningRecord> result = getRecordsByUserIdPaged(userId, page, size);
        result.setSource("mysql");

        // 存入 Redis 缓存，设置过期时间 300 秒
        redisCache.set(cacheKey, result, 300);

        return result;
    }


}